package com.lubansoft.lib_basic.network.converter

import com.google.gson.Gson
import com.google.gson.TypeAdapter
import com.google.gson.reflect.TypeToken
import com.mvvm.start.base.network.DataResponse
import com.mvvm.start.base.network.NetworkRequestException
import com.mvvm.start.base.network.ServerErrorException
import com.mvvm.start.base.utils.getJsonToObject
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.ResponseBody
import okio.Buffer
import retrofit2.Converter
import retrofit2.Retrofit
import java.io.OutputStreamWriter
import java.io.Writer
import java.lang.reflect.Type
import java.nio.charset.Charset

/**
 * 实现参考 com.squareup.retrofit2:converter-gson:2.9.0 中的 GsonConverterFactory
 */
class MVVMStartGsonConverterFactory(private val gson: Gson) : Converter.Factory() {
    companion object {
        fun create(): MVVMStartGsonConverterFactory = MVVMStartGsonConverterFactory(Gson())
    }

    override fun requestBodyConverter(
        type: Type,
        parameterAnnotations: Array<out Annotation>,
        methodAnnotations: Array<out Annotation>,
        retrofit: Retrofit,
    ): Converter<*, RequestBody> {
        val adapter = gson.getAdapter(TypeToken.get(type))
        return MVVMStartGsonRequestBodyConverter(gson, adapter)
    }

    override fun responseBodyConverter(
        type: Type,
        annotations: Array<out Annotation>,
        retrofit: Retrofit,
    ): Converter<ResponseBody, *> {
        val adapter = gson.getAdapter(TypeToken.get(type))
        return MVVMStartGsonResponseBodyConverter(adapter)
    }
}

class MVVMStartGsonRequestBodyConverter<T>(
    private val gson: Gson,
    private val adapter: TypeAdapter<T>,
) : Converter<T, RequestBody> {
    override fun convert(value: T): RequestBody {
        val buffer = Buffer()
        val writer: Writer =
            OutputStreamWriter(buffer.outputStream(), Charset.forName("UTF-8"))
        val jsonWriter = gson.newJsonWriter(writer)
        adapter.write(jsonWriter, value)
        jsonWriter.close()
        return buffer.readByteString()
            .toRequestBody("application/json; charset=UTF-8".toMediaType())
    }

}

class MVVMStartGsonResponseBodyConverter<T>(
    private val adapter: TypeAdapter<T>,
) : Converter<ResponseBody, T> {
    override fun convert(value: ResponseBody): T? {
        val json = value.string()
        val dataResponse = getJsonToObject<DataResponse<T>>(json)
        val result = adapter.fromJson(json)
        if (!dataResponse.isSuccess) {
            // 其他非200错误直接抛出
            NetworkRequestException.instance.onError(dataResponse)
            throw ServerErrorException(json,true)
        }
        value.close()
        return result
        // 原GsonConverterFactory-GsonResponseBodyConverter逻辑
        // val jsonReader = gson.newJsonReader(value.charStream())
        // return value.use {
        //     val result = adapter.read(jsonReader)
        //     if (jsonReader.peek() != JsonToken.END_DOCUMENT) {
        //         throw JsonIOException("JSON document was not fully consumed.")
        //     }
        //     result
        // }
    }


}